﻿using Cognitum.CassandraProviders.Cassandra;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.SessionState;

namespace Cognitum.ProvidersTests
{
    [TestFixture]
    internal class SessionStateProviderTests : BaseProvidersTest
    {
        private HttpContext _context;
        private int _timeout;
        private string sessionId = "partitionKey";

        #region Methods

        [Test]
        public void CreateNewStoreData()
        {
            // Arrange
            // Act
            SessionStateStoreData result = _providerSession.CreateNewStoreData(_context, _timeout);
            // Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(_timeout, result.Timeout);
        }

        [Test]
        public void CreateUninitializedItem()
        {
            // Arrange
            bool locked;
            TimeSpan lockAge;
            object lockId;
            SessionStateActions actions;
            // Act
            // Assert
            Assert.DoesNotThrow(delegate { _providerSession.CreateUninitializedItem(_context, sessionId, _timeout); });

            //Clean
            SessionStateStoreData item = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            _providerSession.RemoveItem(_context, sessionId, lockId, item);
        }

        [Test]
        public void EndRequest()
        {
            // Arrange
            // Act
            // Assert
            Assert.DoesNotThrow(delegate { _providerSession.EndRequest(_context); });
        }

        [Test]
        public void GetItem()
        {
            // Arrange
            bool locked;
            TimeSpan lockAge;
            object lockId;
            SessionStateActions actions;
            _providerSession.CreateUninitializedItem(_context, sessionId, _timeout);
            // Act
            SessionStateStoreData item = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            // Assert
            Assert.IsNotNull(item);
            Assert.AreEqual(20, item.Timeout);
            //Clean
            _providerSession.RemoveItem(_context, sessionId, lockId, item);
        }

        [Test]
        public void GetItemExclusive_ReleaseItemExclusive()
        {
            // Arrange
            bool locked = false;
            TimeSpan lockAge;
            object lockId;
            SessionStateActions actions;
            _providerSession.CreateUninitializedItem(_context, sessionId, _timeout);
            // Act
            SessionStateStoreData item = _providerSession.GetItemExclusive(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            // Assert
            Assert.IsTrue(locked);
            _providerSession.ReleaseItemExclusive(_context, sessionId, lockId);
            Assert.IsNotNull(item);
            Assert.AreEqual(20, item.Timeout);
            item = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            Assert.IsFalse(locked);
            //Clean
            _providerSession.RemoveItem(_context, sessionId, lockId, item);
        }

        [SetUp]
        public override void Init()
        {
            base.Init();
            _providerSession = new CassandraSessionStateProvider();
            _providerSession.Initialize("CustomSessionStateProvider", _conf);
            _context = new HttpContext(new HttpRequest(null, "http://tempuri.org", null), new HttpResponse(null));
            _timeout = 1;
        }

        [Test]
        public void InitializeRequest()
        {
            // Arrange
            // Act
            // Assert
            Assert.DoesNotThrow(delegate { _providerSession.InitializeRequest(_context); });
        }

        [Test]
        public void RemoveItem()
        {
            // Arrange
            bool locked;
            TimeSpan lockAge;
            object lockId;
            SessionStateActions actions;
            _providerSession.CreateUninitializedItem(_context, sessionId, _timeout);
            SessionStateStoreData item = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            // Act
            _providerSession.RemoveItem(_context, sessionId, lockId, item);
            // Assert
            item = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            Assert.IsNull(item);
        }

        [Test]
        public void ResetItemTimeout()
        {
            // Arrange
            bool locked;
            TimeSpan lockAge;
            object lockId;
            SessionStateActions actions;
            _providerSession.CreateUninitializedItem(_context, sessionId, _timeout);
            SessionStateStoreData item = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            Assert.AreEqual(20, item.Timeout);
            // Act
            _providerSession.ResetItemTimeout(_context, sessionId);
            // Assert
            item = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            Assert.AreEqual(1, item.Timeout);
            //Clean
            _providerSession.RemoveItem(_context, sessionId, lockId, item);
        }

        [Test]
        public void SetAndReleaseItemExclusive_OldItem()
        {
            // Arrange
            bool locked;
            TimeSpan lockAge;
            object lockId;
            SessionStateActions actions;
            _providerSession.CreateUninitializedItem(_context, sessionId, _timeout);
            SessionStateStoreData item = _providerSession.GetItemExclusive(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            Assert.IsTrue(locked);
            // Act
            _providerSession.SetAndReleaseItemExclusive(_context, sessionId, item, lockId, false);
            // Assert
            Assert.IsNotNull(item);
            Assert.AreEqual(20, item.Timeout);
            SessionStateStoreData item2 = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            Assert.IsFalse(locked);
            Assert.AreEqual(item.Items, item2.Items);
            //Clean
            _providerSession.RemoveItem(_context, sessionId, lockId, item);
        }

        [Test]
        public void SetAndReleaseItemExclusive_NewItem()
        {
            // Arrange
            bool locked;
            TimeSpan lockAge;
            object lockId;
            SessionStateActions actions;
            _providerSession.CreateUninitializedItem(_context, sessionId, _timeout);
            SessionStateStoreData item = _providerSession.GetItemExclusive(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            Assert.IsTrue(locked);
            // Act
            _providerSession.SetAndReleaseItemExclusive(_context, sessionId, item, lockId, true);
            // Assert
            Assert.IsNotNull(item);
            Assert.AreEqual(20, item.Timeout);
            SessionStateStoreData item2 = _providerSession.GetItem(_context, sessionId, out locked, out lockAge, out lockId, out actions);
            Assert.IsFalse(locked);
            Assert.AreEqual(item.Items, item2.Items);
            //Clean
            _providerSession.RemoveItem(_context, sessionId, lockId, item);
        }

        [Test]
        public void SetItemExpireCallback()
        {
            // Arrange
            SessionStateItemExpireCallback expireCallback = null;
            // Act
            bool result = _providerSession.SetItemExpireCallback(expireCallback);
            // Assert
            Assert.IsFalse(result);
        }

        #endregion Methods
    }
}